﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ICSharpCode.WinFormsUI.Controls.Chart3D
{
    public class Matrix3D
    {
        private Camera camera = new Camera();
        public Camera Camera
        {
            get { return camera; }
        }

        private System.Windows.Forms.Control container = null;

        public Matrix3D(System.Windows.Forms.Control container)
        {
            this.container = container;
        }

        public Point2D Transform2D(Point3D p)
        {
            Point3D pt = Transform3D(p, camera.Beta, camera.Theta);
            return new Point2D(pt.X, pt.Y);
        }

        public Point3D Transform3D(Point3D p, float beta, float theta)
        {
            /*
             * | x |   | cos(beta) -sin(beta) 0 |   | cos(theta) 0 -sin(theta) |   | x0 |
             * | y | = | sin(beta)  cos(beta) 0 | * | 0          1  0          | * | y0 |
             * | z |   | 0          0         1 |   | sin(theta) 0  cos(theta) |   | z0 |
             */
            float x0 = p.X;
            float y0 = p.Y;
            float z0 = p.Z;

            float x1 = (float)(Math.Cos(beta) * x0 - Math.Sin(beta) * y0);
            float y1 = (float)(Math.Sin(beta) * x0 + Math.Cos(beta) * y0);
            float z1 = z0;

            float x2 = (float)(Math.Cos(theta) * x1 - Math.Sin(theta) * z1);
            float y2 = y1;
            float z2 = (float)(Math.Sin(theta) * x1 + Math.Cos(theta) * z1);

            float y3 = -x2; // fix ??
            float x3 = y2;
            float z3 = y3;

            return new Point3D(container.Width / 2 + x3, container.Height / 2 - y3, z3);
        }

        public void Rotate(double x, double y)
        {
            this.camera.ObservationPosition((float)x, (float)y);
            this.container.Invalidate();
        }

        public void RotateX(double x)
        {
            this.camera.ObservationPosition(camera.Theta, (float)x);
            this.container.Invalidate();
        }

        public void RotateY(double y)
        {
            this.camera.ObservationPosition((float)y, camera.Beta);            
            this.container.Invalidate();
        }

    }
}
